package org.example.ymcc.service.impl;

import cn.hutool.cache.Cache;
import com.alibaba.fastjson.JSONObject;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.example.ymcc.constant.CacheConstants;
import org.example.ymcc.constant.MQConstants;
import org.example.ymcc.constant.RConst;
import org.example.ymcc.domain.CourseDoc;
import org.example.ymcc.domain.CourseOrder;
import org.example.ymcc.domain.CourseOrderItem;
import org.example.ymcc.dto.OrderDto;
import org.example.ymcc.dto.OrderPayDto;
import org.example.ymcc.dto.PreOrderDto;
import org.example.ymcc.feignclient.ESFeignClient;
import org.example.ymcc.mapper.CourseOrderItemMapper;
import org.example.ymcc.mapper.CourseOrderMapper;
import org.example.ymcc.result.JsonResult;
import org.example.ymcc.ro.KillOrderRo;
import org.example.ymcc.ro.OrderRo;
import org.example.ymcc.service.ICourseOrderItemService;
import org.example.ymcc.service.ICourseOrderService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.ymcc.util.CodeGenerateUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author zcj
 * @since 2024-06-20
 */
@Service
public class CourseOrderServiceImpl extends ServiceImpl<CourseOrderMapper, CourseOrder> implements ICourseOrderService {
    @Autowired
    private ESFeignClient esFeignClient;
    @Autowired
    private ICourseOrderItemService courseOrderItemService;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public JsonResult placeOrder(OrderRo orderRo,JSONObject login) {
        if (!redisTemplate.hasKey(orderRo.getToken())){
            return JsonResult.error("令牌已过期");
        }
        //删除令牌
        redisTemplate.delete(orderRo.getToken());

        //你在订单里面要获取课程数据？  openfeign
        List<Long> courseIds = orderRo.getCourseIds();
        Double totalAmount = new Double(RConst.Num.DOUBLE_0);
        Double payAmount = new Double(RConst.Num.DOUBLE_0);
        StringBuilder sb = new StringBuilder();
        //生成订单号   唯一的
        String sn = CodeGenerateUtils.generateOrderSn(Long.valueOf(login.get("id").toString()));
        List<CourseOrderItem> list = new ArrayList<>();
        //循环数据
        for (Long courseId : courseIds) {
            JsonResult result = esFeignClient.getCourseDoc(courseId);
            CourseDoc courseDoc = JSONObject.parseObject(JSONObject.toJSONString(result.getData()), CourseDoc.class);
            totalAmount += courseDoc.getPriceOld();
            payAmount += courseDoc.getPrice();
            sb.append(courseDoc.getName());
            //构建课程订单详情
            list.add(buildItem(sn, courseId, courseDoc.getPrice(),courseDoc.getName(),courseDoc.getPic()));
        }
        //保存订单数据
        CourseOrder courseOrder = getCourseOrder(orderRo.getPayType(), login, totalAmount, payAmount, sb, sn,RConst.Num.INT_0);

        OrderPayDto orderPayDto = new OrderPayDto();
        BeanUtils.copyProperties(courseOrder,orderPayDto);
        orderPayDto.setCourseIds(courseIds.stream().map(Object::toString).collect(Collectors.joining(",")));

        sendMQ(sn, list, courseOrder, orderPayDto,login,sb.toString());

        return JsonResult.success().setData(sn);
    }

    private void sendMQ(String sn, List<CourseOrderItem> list, CourseOrder courseOrder, OrderPayDto orderPayDto,JSONObject login,String title) {
        //发送MQ给common服务 进行通知
        Map<String, Object> map = new HashMap<>();
        map.put("userId",login.get("id"));
        map.put("message",title);
        map.put("orderSn",sn);

        rocketMQTemplate.syncSend(MQConstants.COURSE_PLACE_AN_ORDER_TOPIC+":"+MQConstants.COURSE_PLACE_AN_ORDER_TAG,
                MessageBuilder.withPayload(JSONObject.toJSONString(map)).build());


        //发送MQ的事务消息    发送到消费MessageBuilder
        rocketMQTemplate.sendMessageInTransaction(MQConstants.MQ_COURSE_ORDER_PAY_GROUP_TRANSACTION,
                MQConstants.MQ_PAY_ORDER_TOPIC+":"+MQConstants.MQ_PAY_ORDER_TAG,
                MessageBuilder.withPayload(JSONObject.toJSONString(orderPayDto)).build(),
                new OrderDto(courseOrder, list));

        //发送一个延迟消息  15分钟  如果用户不支付 直接修改状态 2取消支付
        rocketMQTemplate.syncSend(MQConstants.ORDER_TIMEOUT_PAY_TOPIC+":"+MQConstants.ORDER_TIMEOUT_PAY_TAG,
                MessageBuilder.withPayload(sn).build(),RConst.Num.INT_2000,RConst.Num.INT_2);
    }

    /**
     * 秒杀下单
     * @param orderRo
     * @param login
     * @return
     */
    @Override
    public JsonResult killPlaceOrder(KillOrderRo orderRo, JSONObject login) {
        //防重提交令牌
        if (!redisTemplate.hasKey(orderRo.getToken())){
            return JsonResult.error("令牌已过期");
        }
        //删除令牌
        redisTemplate.delete(orderRo.getToken());
        //获取预订单数据
        PreOrderDto dto = (PreOrderDto)redisTemplate.opsForValue().get(CacheConstants.KEY_PREFIX_PRE_ORDER + ":" + orderRo.getOrderNo());
        //构建订单数据
        CourseOrder courseOrder = getCourseOrder(orderRo.getPayType(), login, dto.getPrice().doubleValue(), dto.getPrice().doubleValue(), new StringBuilder(dto.getCourseName()), orderRo.getOrderNo(), RConst.Num.INT_1);
        //构建订单详情
        CourseOrderItem courseOrderItem = buildItem(orderRo.getOrderNo(), dto.getCourseId(), dto.getPrice().doubleValue(), dto.getCourseName(), dto.getCoursePic());
        //构建courseIds
        OrderPayDto orderPayDto = new OrderPayDto();
        BeanUtils.copyProperties(courseOrder,orderPayDto);
        orderPayDto.setCourseIds(dto.getCourseId().toString());
        //构建订单详情列表
        List<CourseOrderItem> list = new ArrayList<>();
        list.add(courseOrderItem);
        //发送MQ
        sendMQ(orderRo.getOrderNo(), list, courseOrder, orderPayDto,login,dto.getCourseName());
        //返回订单号
        return JsonResult.success().setData(orderRo.getOrderNo());
    }

    private static CourseOrder getCourseOrder(Integer payType, JSONObject login, Double totalAmount, Double payAmount, StringBuilder sb, String sn,Integer orderType) {
        CourseOrder courseOrder = new CourseOrder();
        courseOrder.setCreateTime(new Date());
        courseOrder.setOrderNo(sn);
        courseOrder.setTotalAmount(new BigDecimal(totalAmount));
        courseOrder.setPayAmount(new BigDecimal(payAmount));
        courseOrder.setDiscountAmount(new BigDecimal(totalAmount - payAmount));
        courseOrder.setTotalCount(RConst.Num.INTEGER_1);
        courseOrder.setStatusOrder(RConst.Num.INT_0);
        courseOrder.setUserId(Long.valueOf(login.get("id").toString()));
        courseOrder.setTitle(sb.toString());
        courseOrder.setPayType(payType);
        courseOrder.setOrderType(orderType);
        return courseOrder;
    }

    private static CourseOrderItem buildItem(String sn, Long courseId, Double price,String name,String pic) {
        CourseOrderItem courseOrderItem = new CourseOrderItem();
        courseOrderItem.setAmount(new BigDecimal(price));
        courseOrderItem.setPrice(new BigDecimal(price));
        courseOrderItem.setCount(RConst.Num.INT_1);
        courseOrderItem.setCourseId(courseId);
        courseOrderItem.setCourseName(name);
        courseOrderItem.setCoursePic(pic);
        courseOrderItem.setOrderNo(sn);
        return courseOrderItem;
    }
}
